package com.hanserwei.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hanserwei.domain.dataobject.Orders;
import com.hanserwei.domain.dataobject.Products;
import com.hanserwei.domain.mapper.OrdersMapper;
import com.hanserwei.service.OrdersService;
import com.hanserwei.service.ProductsService;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scripting.support.ResourceScriptSource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Collections;

@SuppressWarnings("ALL")
@Service
@Slf4j
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    @Resource
    private ProductsService productsService;

    @Resource
    private TransactionTemplate transactionTemplate;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private ThreadPoolTaskExecutor taskExecutor;

    @Override
    public synchronized boolean createOrder(Orders orders) {
        // 商品ID，用于查询库存
        Long productId = orders.getProductId();
        // 购买数量用于比较库存是否充足
        Integer quantity = orders.getQuantity();

        Products stockProduct = productsService.getOne(new LambdaQueryWrapper<>(Products.class)
                .select(Products::getStock)
                .eq(Products::getId, productId));

        // 库存不足，直接返回false
        if (stockProduct.getStock() < quantity) {
            log.warn("库存不足，无法创建订单");
            return false;
        }

        Boolean result = transactionTemplate.execute(status -> {
            try {
                // 更新库存
                productsService.update(new LambdaUpdateWrapper<Products>()
                        .eq(Products::getId, productId)
                        .set(Products::getStock, stockProduct.getStock() - quantity));

                // 创建订单
                this.save(orders);
                log.info("创建订单成功");
                return true;
            } catch (Exception e) {
                log.error("创建订单失败", e);
                status.setRollbackOnly();
                return false;
            }
        });

        if (result != null) {
            return result;
        }
        return false;
    }

    @Override
    @SneakyThrows
    public boolean createOrder2(Orders orders) {
        // 获取商品ID,用来生成RedisKey
        Long productId = orders.getProductId();
        // 购买数量
        Integer quantity = orders.getQuantity();

        DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource("lua/checkStock.lua")));
        redisScript.setResultType(Long.class); // 脚本返回类型是 Long

        String redisKey = "product:stock:" + productId;
        log.info("Redis Key:{}", redisKey);

        // 调用Lua脚本
        Long result = stringRedisTemplate.execute(
                redisScript,
                Collections.singletonList(redisKey),        // KEYS[1]
                String.valueOf(quantity)                    // ARGV[1]
        );

        log.info("Redis 扣减结果:{}", result);

        // 3. 检查 Redis 扣减结果
        if (result == null || result.intValue() != 1) {
            // Redis 扣减失败 (库存不足)
            return false;
        }

        // --- Redis 扣减成功，开始数据库持久化 ---
        try {
            // 异步执行 DB 事务
            taskExecutor.execute(() -> {
                boolean dbSuccess = transactionTemplate.execute(status -> {
                    try {
                        // 更新库存
                        boolean updated = productsService.update(new LambdaUpdateWrapper<Products>()
                                .eq(Products::getId, productId)
                                .ge(Products::getStock, quantity)
                                .setSql("stock = stock - " + quantity));

                        if (!updated) {
                            status.setRollbackOnly();
                            return false;
                        }
                        // 创建订单
                        this.save(orders);
                        return true;

                    } catch (Exception e) {
                        log.error("创建订单事务执行失败，需要回滚！", e);
                        status.setRollbackOnly();
                        return false;
                    }
                });
                // 如果 DB 事务失败, 则执行 Redis 库存补偿
                if (!dbSuccess) {
                    stringRedisTemplate.opsForValue().increment(redisKey, quantity);
                    log.warn("DB 事务失败，已将 Redis Key:{} 的库存补偿:{}!", redisKey, quantity);
                }
            });
            return true;
        } catch (Exception e) {
            log.error("订单创建失败，执行 Redis 补偿！", e);
            stringRedisTemplate.opsForValue().increment(redisKey, quantity);
            return false;
        }
    }
}
